#include "common.h"

#include <ctime>
#include <iomanip>
#include "bmp.h"

ostream &operator <<(ostream &os, Vec a){
    os << "(" << a.x << "," << a.y << "," << a.z << ")";
    return os;
}


ostream &operator <<(ostream &os, Ray col){
    os << col.ori << " ->>>>> " << col.dir;
    return os;
}

ostream &operator <<(ostream &os, RGB col){
    os << "(" << col.r <<" " << col.g << " " << col.b << ")";
    return os;
}

ostream &operator <<(ostream &os, Matrix mm)
{
    os << setprecision(2);
    for (int i = 0 ; i < 4; i++){
        os << "(";
        for (int j = 0 ; j < 4; j++){
            os << mm.matrix[i][j] << " ";
        }
        os << ")\n";
    }
    return os;
}

double ran()
{
    int random = rand();
    return 1.0 * random / 32767;
}


int getFather(int x, int *father)
{
    if (father[x] == x) return x;
    father[x] = getFather(father[x], father);
    return father[x];
}


Vec Matrix::solve()
{
    double **a;
    a = new double*[3];
    for (int i = 0 ; i < 3; i++){
        a[i] = new double[4];
        for (int j = 0 ; j < 4; j++){
            a[i][j] = this->matrix[i][j];
        }
    }
    Vec ans = Vec(0,0,0);
    for (int i = 0; i < 3; i++){
        if (fabs(a[i][i]) <= zero){
            for (int j = i + 1; j < 3; j++){
                if (fabs(a[j][i]) > zero){
                    double* tmp = a[i];
                    a[i] = a[j];
                    a[j] = tmp;
                    break;
                }
            }
        }
        if (fabs(a[i][i]) > zero){
            for (int j = 0; j < 3; j++){
                if (j == i) continue;
                double w = a[j][i] / a[i][i];
                for (int k = 0 ; k < 4; k++){
                    a[j][k] -= w * a[i][k];
                }
            }
        }else{
            return ans;
        }
    }


    ans.x = -a[0][3] / a[0][0];
    ans.y = -a[1][3] / a[1][1];
    ans.z = -a[2][3] / a[2][2];
    for (int i = 0 ; i < 3; i++){
        delete []a[i];
    }
    delete[] a;
    return ans;
}



void Material::setTexture(string file){
    bmp = new Bmp();
    bmp->Input(file);
    texture = 1;
}

RGB Material::getColor(double x, double y){
    if (texture == 0){
        return color;
    }else {
        RGB a = bmp->GetSmoothRGB((1 - y), (1 - x));
        return a;
    }
}
